package com.sylli.oeuf.server.game.logic;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sylli.oeuf.server.game.logic.BattleActor.Type;
import com.sylli.oeuf.server.game.logic.invocation.InvocationEvent;
import com.sylli.oeuf.server.object.transferable.PostBattleResponseTO;

public class Battle {

	private Swapper<BattleActor> swapper = null;
	
	private static Logger log = LoggerFactory.getLogger( "game.battle.logic" );
	
	public Battle(BattleActor a, BattleActor b) {
		swapper = new Swapper<BattleActor>(a,b);
		log.info("Starting a new battle: " + a.getName() + " vs " + b.getName());
		if (a.getUsingPlan() == null) {
			log.warn(a.getName() + "'s plan is not set, using default plan.");
			a.setUsingPlan(Plan.defaultPlan);
		}
		if (b.getUsingPlan() == null) {
			log.warn(b.getName() + "'s plan is not set, using default plan.");
			b.setUsingPlan(Plan.defaultPlan);
		}
	}
	
	public void startBattle(PostBattleResponseTO post) {
		
		swapper.getHead().initializeActor(post, swapper.getTail());
		swapper.getTail().initializeActor(post, swapper.getHead());

		// dispatch the BATTLE START
		swapper.getHead().dispatchEvent(InvocationEvent.STD_IE_ON_START, null);
		swapper.getTail().dispatchEvent(InvocationEvent.STD_IE_ON_START, null);
		
		while (!swapper.getHead().isDefeated() && !swapper.getTail().isDefeated()) {
			swapper.getHead().newTurn();
			
			// apply tick & decay it.
			swapper.getHead().dispatchEvent(InvocationEvent.STD_IE_ON_TICK, null);
			swapper.getHead().recompute();
			swapper.getHead().decayBuffAndDebuff();
			
			// get caster and selected skill
			swapper.getHead().dispatchEvent(InvocationEvent.STD_IE_ON_ATTACK, null);
			swapper.getTail().dispatchEvent(InvocationEvent.STD_IE_ON_DEFEND, null);
			
			// swap the turn.
			swapper.swap();
		}
		
		swapper.getHead().reverseSnap();
		swapper.getTail().reverseSnap();
		
		BattleActor winner = null;
		if(swapper.getHead().isDefeated() && swapper.getTail().isDefeated()) {
			post.setFlag(PostBattleResponseTO.POSTRESP_BATTLE_DRAW);
			return;
		} else {
			winner = (swapper.getHead().isDefeated())?swapper.getTail():swapper.getHead();
		}

		post.setFlag(
				winner.getType().equals(Type.Player)?
					PostBattleResponseTO.POSTRESP_BATTLE_WIN:
					PostBattleResponseTO.POSTRESP_BATTLE_LOSE
				);
		
		log.debug("post: "+ post);
	}
	
}
